package cn.kk.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import javax.annotation.PreDestroy;
import java.util.concurrent.*;

/**
 * 线程池配置类
 * @author liujunkai
 * @date 2023/3/23 10:56
 */
@Slf4j
@Configuration
public class ThreadPoolConfig {

    private ThreadPoolExecutor threadPoolExecutor;

    /*
    *  什么是CPU密集型和IO密集型服务器？
       CPU密集型服务器是指需要大量的CPU处理能力来完成任务的服务器。这些服务器通常会运行计算密集型应用程序，例如数学计算、编码解码、3D建模等。这些应用程序需要大量的CPU计算能力来完成任务，因此CPU利用率较高。
       IO密集型服务器是指需要大量的磁盘I/O或网络I/O操作来完成任务的服务器。这些服务器通常会运行文件服务器、数据库服务器、Web服务器等应用程序。这些应用程序需要大量的磁盘I/O和网络I/O操作，而不需要太多的CPU计算能力。

       如何区分？
       1.CPU密集型服务器通常具有高CPU利用率，而IO密集型服务器通常具有低CPU利用率。如果服务器的CPU利用率非常高（例如，超过80％），则它可能是CPU密集型的。相反，如果CPU利用率较低，但磁盘I/O利用率较高，则服务器可能是IO密集型的。
       2.如果服务器处理大量的数据库查询、文件读写、网络通信等，它可能是IO密集型的。这些操作需要大量的磁盘I/O和网络I/O，而不需要太多的CPU计算能力。相反，如果服务器运行大量的CPU密集型应用程序，例如视频编码、图像处理、数学计算等，它可能是CPU密集型的。

       门店房匠系统目前是属于IO密集型应用，所以要尽量的加大线程数的利用，加大IO操作的并发量，榨取CPU资源，减少CPU的空闲
       反之如果是CPU密集型应用则要减少线程数，从而减少线程的上下文切换，防止CPU资源的浪费
    */

    private static final int CPU_CORES = Runtime.getRuntime().availableProcessors();                       // CPU核心数
    private static final double BLOCKING_COEFFICIENT = 0.8;                                                // 阻塞系数
    private static final int CPU_INTENSIVE = CPU_CORES + 1;                                                // CPU密集型线程数
    private static final int IO_INTENSIVE = CPU_CORES * 2;                                                 // IO密集型线程数
    private static final int IO_INTENSIVE_PLUS = (int) (CPU_CORES / (1 - BLOCKING_COEFFICIENT));           // IO密集型线程数另一个公式
    private static final int KEEP_ALIVE_TIME = 60;                                                         // 存活时间
    private static final TimeUnit UNIT = TimeUnit.SECONDS;                                                 // 存活时间单位
    private static final BlockingQueue<Runnable> WORK_QUEUE = new LinkedBlockingDeque<>(500);      // 任务队列
    private static final ThreadFactory THREAD_FACTORY = new CustomizableThreadFactory("business-thread");  // 线程工厂
    private static final RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.AbortPolicy();          // 拒绝策略

    @Bean
    public ThreadPoolExecutor getThreadPoolExecutor() {
        threadPoolExecutor = new ThreadPoolExecutor(
                CPU_CORES,              // 核心线程数
                IO_INTENSIVE,           // 最大线程数
                KEEP_ALIVE_TIME,        // 存活时间
                UNIT,                   // 存活时间单位
                WORK_QUEUE,             // 任务队列
                THREAD_FACTORY,         // 线程工厂
                HANDLER                 // 拒绝策略
        );
        return threadPoolExecutor;
    }

    @PreDestroy
    public void destroy() {
        // 执行shutdown，将会拒绝新任务提交到线程池；待执行的任务不会取消，正在执行的任务也不会取消，将会继续执行直到结束
        threadPoolExecutor.shutdown();
        try {
            // 超时等待线程池完毕
            if (!threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS)) {
                threadPoolExecutor.shutdownNow();
                log.info("线程池成功关闭");
                if (!threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS)) {
                    log.error("线程池未能正常关闭，等待GC回收");
                }
            }
        } catch (InterruptedException e) {
            threadPoolExecutor.shutdownNow();
            log.error("关闭线程池捕获异常：" + e);
        }
    }

}